#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , serial(new QSerialPort)
    , authpcs(new QProcess)
    , rptimer(new QTimer)
{
    ui->setupUi(this);

    paused = false;
    sendcnt = 0;
    recvcnt = 0;

    initial_nable();

    connect(ui->actionExit,SIGNAL(triggered()),this,SLOT(close()));
    connect(serial,SIGNAL(readyRead()),this,SLOT(on_Serial_ReadyRead()));
    connect(rptimer,SIGNAL(timeout()),this,SLOT(on_pushButton_Send_clicked()));
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_scan_clicked()
{
    //Rescan Serial ports
    QString portName;
    QSerialPortInfo info;

    ui->comboBox_serialport->clear();

    foreach(info,QSerialPortInfo::availablePorts()){
        serial->setPort(info);
        portName = info.portName();

        ui->comboBox_serialport->addItem(portName);
    }
    if(ui->comboBox_serialport->currentIndex() == -1)
        ui->pushButton_open->setDisabled(true);
    else
        ui->pushButton_open->setEnabled(true);
}

void MainWindow::on_pushButton_open_clicked()
{
    const int baud_rate_map[]={QSerialPort::Baud1200,QSerialPort::Baud2400,QSerialPort::Baud4800,QSerialPort::Baud9600,\
                               QSerialPort::Baud19200,QSerialPort::Baud38400,QSerialPort::Baud57600,QSerialPort::Baud115200};
    const int data_bits_map[]={QSerialPort::Data5,QSerialPort::Data6,QSerialPort::Data7,QSerialPort::Data8};
    const int stop_bits_map[]={QSerialPort::OneStop,QSerialPort::OneAndHalfStop,QSerialPort::TwoStop};
    const int parity_map[]={QSerialPort::NoParity,QSerialPort::EvenParity,QSerialPort::OddParity,QSerialPort::SpaceParity,QSerialPort::MarkParity};
    const int flowctl_map[]={QSerialPort::NoFlowControl,QSerialPort::HardwareControl,QSerialPort::SoftwareControl};

    serial->setPortName(ui->comboBox_serialport->currentText());
    serial->setBaudRate(baud_rate_map[ui->comboBox_baudrate->currentIndex()]);
    serial->setDataBits(QSerialPort::DataBits(data_bits_map[ui->comboBox_databits->currentIndex()]));
    serial->setStopBits(QSerialPort::StopBits(stop_bits_map[ui->comboBox_stopbits->currentIndex()]));
    serial->setParity(QSerialPort::Parity(parity_map[ui->comboBox_parity->currentIndex()]));
    serial->setFlowControl(QSerialPort::FlowControl(flowctl_map[ui->comboBox_flowctrl->currentIndex()]));

    authpcs->start("pkexec chmod 777 /dev/" + serial->portName());
    authpcs->waitForFinished();

    if (!serial->open(QIODevice::ReadWrite)) {
        QMessageBox::warning(this,"Warning","Open serial port fail!\n Please see the the information window to solve problem.");
    }
    else{

        serial->clear();
        connected_nable();
    }
}

void MainWindow::on_Serial_ReadyRead()
{
    QByteArray recvArray;
    QString recvStr;

    recvArray = serial->readAll();
    recvStr = QString(recvArray);

    recvcnt += recvStr.count();
    refreshrecv(recvStr,false);

}

void MainWindow::on_pushButton_close_clicked()
{
    serial->close();
    disconnected_nable();

    paused = false;
}

void MainWindow::on_pushButton_pause_clicked()
{
    if( paused == false ) {
        paused = true;
        ui->pushButton_pause->setText("start");
    } else{
        paused = false;
        ui->pushButton_pause->setText("pause");
    }
}

void MainWindow::connected_nable()
{
    ui->comboBox_serialport->setDisabled(true);
    ui->comboBox_baudrate->setDisabled(true);
    ui->comboBox_databits->setDisabled(true);
    ui->comboBox_stopbits->setDisabled(true);
    ui->comboBox_parity->setDisabled(true);
    ui->comboBox_flowctrl->setDisabled(true);

    ui->pushButton_close->setEnabled(true);
    ui->pushButton_pause->setEnabled(true);
    ui->pushButton_open->setDisabled(true);
    ui->pushButton_scan->setDisabled(true);
    ui->pushButton_Send->setEnabled(true);

    ui->checkBox_repeat->setEnabled(true);
}

void MainWindow::disconnected_nable()
{
    ui->pushButton_open->setEnabled(true);
    ui->pushButton_scan->setEnabled(true);
    ui->pushButton_pause->setDisabled(true);
    ui->pushButton_Send->setDisabled(true);
    ui->pushButton_close->setDisabled(true);

    ui->comboBox_serialport->setEnabled(true);
    ui->comboBox_baudrate->setEnabled(true);
    ui->comboBox_databits->setEnabled(true);
    ui->comboBox_stopbits->setEnabled(true);
    ui->comboBox_parity->setEnabled(true);
    ui->comboBox_flowctrl->setEnabled(true);

    ui->checkBox_repeat->setChecked(false);
    ui->checkBox_repeat->setDisabled(true);
}

void MainWindow::initial_nable()
{
    on_pushButton_scan_clicked();
    ui->comboBox_serialport->setCurrentIndex(0);
    ui->comboBox_baudrate->setCurrentIndex(3);
    ui->comboBox_databits->setCurrentIndex(3);
    ui->comboBox_stopbits->setCurrentIndex(0);
    ui->checkBox_clearcnt->setChecked(false);
    clearcnt = false;
    ui->checkBox_disptime->setChecked(true);
    timetrap = true;
    ui->checkBox_dispsend->setChecked(true);
    dispsend = true;

    ui->pushButton_close->setDisabled(true);
    ui->pushButton_pause->setDisabled(true);
    ui->pushButton_Send->setDisabled(true);

    ui->checkBox_repeat->setChecked(false);
    ui->checkBox_repeat->setDisabled(true);

    ui->TextEdit_Recv->setReadOnly(true);
    ui->labelRBytes->setText(QString::number(recvcnt,10));
    ui->labelSBytes->setText(QString::number(sendcnt,10));
}

void MainWindow::refreshrecv(QString str,bool send)
{
    ui->labelSBytes->setText(QString::number(sendcnt,10));
    ui->labelRBytes->setText(QString::number(recvcnt,10));
    if(str.isEmpty() or paused)
        return;

    QString disbuf;
    if(disphex)
        disbuf = str.toLatin1().toHex(' ').toUpper();
    else
        disbuf = str;

    if(send)
        disbuf = "(send): " + disbuf;
    else
        disbuf = "(Recv): " + disbuf;

    if(timetrap){
        QTime time = QTime::currentTime();
        disbuf = time.toString("hh:mm:ss.zzz") + disbuf;
    }

    if(send)
        ui->TextEdit_Recv->setTextColor(Qt::blue);
    else
        ui->TextEdit_Recv->setTextColor(Qt::red);
    ui->TextEdit_Recv->append(disbuf);

}

void MainWindow::on_pushButton_clrSend_clicked()
{
    if(clearcnt)
        sendcnt = 0;
    ui->TextEdit_Send->clear();
    ui->labelSBytes->setText(QString::number(sendcnt,10));
}

void MainWindow::on_pushButton_clrRecv_clicked()
{
    if(clearcnt)
        recvcnt = 0;
    ui->TextEdit_Recv->clear();
    ui->labelRBytes->setText(QString::number(recvcnt,10));
}

void MainWindow::on_checkBox_clearcnt_toggled(bool checked)
{
    clearcnt = checked;
}

void MainWindow::on_pushButton_Send_clicked()
{
    QString sendbuff = ui->TextEdit_Send->toPlainText();
    if(sendbuff.isEmpty())
    {
        QMessageBox::information(this,"Warnning","Send buffer is Empty!\nPlease fill it to Send!");
        return;
    }

    if(sendhex)
    {
        //convert to raw;
        sendbuff.remove(' ');
        QByteArray sendba = QByteArray::fromHex(sendbuff.toLatin1());
        sendbuff = sendba;
    }

    serial->write(sendbuff.toLatin1());

    sendcnt += sendbuff.count();

    if(dispsend)
        refreshrecv(sendbuff,true);
}

void MainWindow::on_checkBox_disptime_toggled(bool checked)
{
    timetrap = checked;
}

void MainWindow::on_checkBox_dispsend_toggled(bool checked)
{
    dispsend = checked;
}

void MainWindow::on_actionSave_triggered()
{
    QString filepath = QFileDialog::getSaveFileName(this,"Save to file",".","txt file:(*.txt)");
    QFile file(filepath);

    if(!file.open(QFile::WriteOnly))
    {
        QMessageBox::warning(this,"Warnning","Could not open file!\nPlease checkout!");
        return;
    }

    QTextStream qts(&file);
    qts << ui->TextEdit_Recv->document()->toPlainText();

    file.close();
}

void MainWindow::on_actionLoad_triggered()
{
    QString filepath = QFileDialog::getOpenFileName(this,"Load from file",".","text file:(*.txt)");
    QFile file(filepath);

    if(!file.open(QFile::ReadOnly))
    {
        QMessageBox::warning(this,"Warnning","Could not open file!");
        return;
    }

    QTextStream qts(&file);
    QString sendbuf = qts.readAll();

    ui->TextEdit_Send->setPlainText(sendbuf);

    file.close();

}

void MainWindow::on_radioButton_rec_hex_toggled(bool checked)
{
    disphex = checked;
}

void MainWindow::on_radioButton_rec_ascii_toggled(bool checked)
{
    disphex = not checked;
}

void MainWindow::on_actionAbout_XSerial_triggered()
{
    QAboutDialog *dlg = new QAboutDialog();
    dlg->setModal(true);
    dlg->show();
}

void MainWindow::on_radioButton_send_ascii_toggled(bool checked)
{
    sendhex = not checked;
}

void MainWindow::on_radioButton_send_hex_toggled(bool checked)
{
    sendhex = checked;
}

void MainWindow::on_checkBox_repeat_toggled(bool checked)
{
    if(checked)
        rptimer->start(ui->spinBox_repeat->value());
    else
        rptimer->stop();
}

void MainWindow::on_spinBox_repeat_valueChanged(int arg1)
{
    rptimer->setInterval(arg1);
}
